package com.hqyj.javaSpringBoot.modules.account.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hqyj.javaSpringBoot.modules.account.dao.RoleDao;
import com.hqyj.javaSpringBoot.modules.account.dao.UserDao;
import com.hqyj.javaSpringBoot.modules.account.dao.UserRoleDao;
import com.hqyj.javaSpringBoot.modules.account.entity.*;
import com.hqyj.javaSpringBoot.modules.account.service.UserService;
import com.hqyj.javaSpringBoot.modules.common.entiy.ResultEntity;
import com.hqyj.javaSpringBoot.util.MD5Util;
import com.hqyj.javaSpringBoot.util.RedisUtils;
import com.hqyj.javaSpringBoot.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private UserRoleDao userRoleDao;
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private RedisUtils redisUtils;

    private static final Logger LOGGER= LoggerFactory.getLogger(UserServiceImpl.class);


    @Override
    @Transactional
    public ResultEntity<User> insertUser(User user) {
        List<User> users = Optional.ofNullable(userDao.getUserByUserNameorEmail(
                user.getUserName(), user.getEmail())).
                orElse(Collections.emptyList());
        if (!users.isEmpty()){
            return new  ResultEntity<User>(ResultEntity.ResultStatus.FAILED.code,
                    "userName or userEamil is exist",user);
        }
        if (StringUtils.isBlank(user.getUserImage())){
            //给定一个默认头像
            user.setUserImage("/images/123.jpg");
        }

        user.setCreateDate(LocalDateTime.now());
        user.setPassword(MD5Util.getMD5(user.getPassword()));
        userDao.insertUser(user);

        if (user.getRoles()!=null){
            user.getRoles().stream().forEach(item->{
                userRoleDao.insertUserRole(new UserRole(user.getId(),item.getId()));});
        }else {
            //给定一个默认角色id
            List<Role> staff = roleDao.getRoleByRoleName("staff");
            int roleId=staff.get(0).getId();
            userRoleDao.insertUserRole(new UserRole(user.getId(),roleId));
        }
        return new  ResultEntity<User>(ResultEntity.ResultStatus.SUCCESS.code,
                "insert success",user);
    }

    @Override
    @Transactional
    public ResultEntity<User> deleteUser(int id) {
        userDao.deleteUser(id);
        userRoleDao.deleteUserRoleByUserId(id);
        return new  ResultEntity<User>(ResultEntity.ResultStatus.SUCCESS.code,
                "delete success");
    }

    @Override
    @Transactional
    public ResultEntity<User> updateUser(User user) {
        user.setPassword(MD5Util.getMD5(user.getPassword()));
        userDao.updateUser(user);
        if (user.getRoles()!=null && !user.getRoles().isEmpty()){
            userRoleDao.deleteUserRoleByUserId(user.getId());
            user.getRoles().stream().forEach(item->{
                userRoleDao.insertUserRole(new UserRole(user.getId(),item.getId()));});
        }

        Subject subject=SecurityUtils.getSubject();
        Session session = subject.getSession();
        session.setAttribute("user",user);

        PrincipalCollection oldPrincipal = subject.getPrincipals();
        String realmName = oldPrincipal.getRealmNames().iterator().next();
        SimplePrincipalCollection newPrincipal =
                new SimplePrincipalCollection(user, realmName);
        subject.runAs(newPrincipal);

        return new  ResultEntity<User>(ResultEntity.ResultStatus.SUCCESS.code,
                "update success",user);
    }

    @Override
    public User getUserByUserId(int id) {
        return userDao.getUserByUserId(id);
    }

    @Override
    public User getUserByUserName(String userName) {
        return userDao.getUserByUserName(userName);
    }

    @Override
    public ResultEntity<User> getUserLogin(User user) {

        //连续五次输错密码，将锁住30秒
        String key=String.format("login_error_%s",user.getUserName());
        Object temp = redisUtils.get(key);
        int count= temp == null ? 0:(int) temp;
        if (count>5){
            return new ResultEntity<>(ResultEntity.ResultStatus.FAILED.code,
                    "请30秒后再尝试登录");
        }


        Subject subject= SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(user.getUserName(),
                MD5Util.getMD5(user.getPassword()));
        token.setRememberMe(user.getRememberMe());

        try {
            //身份验证,登录验证
            subject.login(token);
            //当页面存在shiro标签或者注解是时，检查角色
            subject.checkRoles();

            Session session = subject.getSession();
            //获取myrealm返回的user对象
            session.setAttribute("user",subject.getPrincipal());

        }catch (Exception e){
            e.printStackTrace();
            LOGGER.debug(e.getMessage());

            //登录失败累计登录次数
            if (count <4 ){
                redisUtils.increment(key,1);
                return new ResultEntity<User>(ResultEntity.ResultStatus.FAILED.code,
                        String.format("已经输错%s次,再输错%s次，将多锁定账号30s",count+1,4-count));
            }else {
                //锁定30秒后，过期清除该key
                redisUtils.expire(key,30);
                return new ResultEntity<User>(ResultEntity.ResultStatus.FAILED.code,
                        String.format("账号密码错误输入五次,请30秒后再尝试登录"));
            }
        }
        redisUtils.delete(key);
        return new ResultEntity<>(ResultEntity.ResultStatus.SUCCESS.code,
                "login success",user);
    }

    @Override
    public PageInfo<User> getUserBySearch(UserSearchBean userSearchBean) {
        userSearchBean.initSerchBean();
        PageHelper.startPage(userSearchBean.getCurrentPage(),userSearchBean.getPageSize());
        return new PageInfo<User>(Optional.ofNullable(userDao.getUserBySearch(userSearchBean)).
                orElse(Collections.emptyList()));
    }

    @Override
    public List<User> getUsers() {
        return userDao.getUsers();
    }

    @Override
    public ResultEntity<User> updateUserPassword(User user,String oldPassWord) {
        if (!userDao.getUserByUserName(user.getUserName()).getPassword().
                equals(MD5Util.getMD5(oldPassWord))){
            return new  ResultEntity<User>(ResultEntity.ResultStatus.FAILED.code,
                    "原密码输入错误，请重新输入");
        }
        user.setPassword(MD5Util.getMD5(user.getPassword()));
        userDao.updateUserPassword(user);
        return new  ResultEntity<User>(ResultEntity.ResultStatus.SUCCESS.code,
                "密码修改成功");
    }

    @Override
    public void logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
    }

    public static void main(String[] args) {
        User user = new User();
        user.setCreateDate(LocalDateTime.now());
        System.out.println(String.valueOf(user.getCreateDate()));
    }
}
